package com.baijia.web.service.impl;

import com.baijia.authentication.principal.Credentials;
import com.baijia.dao.PassportDao;
import com.baijia.dao.ThirdLoginAccountDao;
import com.baijia.dao.po.Passport;
import com.baijia.exception.ErrorCode;
import com.baijia.services.PassportService;
import com.baijia.util.JigouPasswordUtil;
import com.baijia.util.MobileLoginUtil;
import com.baijia.util.RandomStringGenerator;
import com.baijia.util.RedisUtil;
import com.baijia.util.SMSUtils;
import com.baijia.web.dto.response.MobileResponse;
import com.baijia.web.service.IPassportValidateService;
import com.baijia.web.vo.BindPassportVO;
import com.baijia.web.vo.PassportRequestVO;
import com.baijia.web.vo.PasswordRequestVO;
import com.baijia.web.vo.ResetPasswordVO;

import com.google.code.kaptcha.Constants;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * Created by dudu on 16/7/9.
 */
@Service
public class PassportValidateServiceImpl implements IPassportValidateService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private PassportService passportService;

    @Resource
    private RandomStringGenerator randomStringGenerator;

    @Resource
    private ThirdLoginAccountDao thirdLoginAccountDao;

    @Resource
    private PassportDao passportDao;

    @Override
    public boolean validateLoginParams(PassportRequestVO passportRequestVO, MobileResponse response) {
        if (StringUtils.isBlank(passportRequestVO.getUsername())) {
            response.fail().msg(ErrorCode.MOBILE_NULL_ERROR.getMessage());
            return false;
        }
        if (StringUtils.isBlank(passportRequestVO.getCode())) {
            response.fail().msg(ErrorCode.CODE_NULL_ERROR.getMessage());
            return false;
        }
        if (!MobileLoginUtil.validPasscode(passportRequestVO.getUsername(), passportRequestVO.getCode())) {
            response.fail().msg(ErrorCode.CODE_INVALID_ERROR.getMessage());
            return false;
        }

        return true;
    }

    @Override
    public boolean validateSmsCode(String mobile, HttpServletRequest request, String code, MobileResponse response) {
        if (StringUtils.isBlank(mobile)) {
            response.fail().msg(ErrorCode.MOBILE_NULL_ERROR.getMessage());
            return false;
        }
        if (StringUtils.isBlank(code)) {
            response.fail().msg(ErrorCode.CODE_NULL_ERROR.getMessage());
            return false;
        }
        if (passportService.existedUser(mobile, Integer.valueOf(request.getParameter(Credentials.APPID)))) {
            response.fail().msg(ErrorCode.MOBILE_EXIST_ERROR.getMessage());
            return false;
        }
        if (!MobileLoginUtil.validPasscode(mobile, code)) {
            response.fail().msg(ErrorCode.CODE_INVALID_ERROR.getMessage());
            return false;
        }
        return true;
    }

    @Transactional
    @Override
    public boolean validateMobileLoginSms(String mobile, HttpServletRequest request, MobileResponse response) {
        String appId = request.getParameter(Credentials.APPID);
        if (passportService.existedUser(mobile, Integer.valueOf(appId))) {
            return true;
        } else {// passport account is not exist, create a passport account.
            if (StringUtils.isNotBlank(request.getParameter("create"))
                && Integer.valueOf(request.getParameter("create")) > 0) {
                Passport passport = new Passport();
                passport.setMobile(mobile);
                String password = randomStringGenerator.getRandomString(8);
                String pwdHash = JigouPasswordUtil.createHash(password);
                passport.setPassword(pwdHash);
                passport.setMobileVerify(Passport.MobileVerify.YES.getId());
                if (passportService.createUser(passport, request) > 0) {
                    SMSUtils.sendByCode(mobile,
                        String.format(MobileLoginUtil.LOGIN_PASSWORD_TEMPLATE, mobile, password));
                } else {
                    logger.info("fail to create a user account, mobile:{}", passport.getUsername());
                    response.fail().msg("fail to create a user account.");
                    return false;
                }
            } else {
                response.fail().msg(ErrorCode.CREDENTIALS_ERROR.getMessage());
                return false;
            }

            // Long passportId = passportService.createAccount(passport);
            // /** create user success, send pwd to user */
            // if(passportId > 0) {
            // passport.setId(passportId);
            // if(passportService.synData(passport) <= 0) {
            // response.fail().msg(ErrorCode.SYN_DATA_ERROR.getMessage());
            // return false;
            // }
            // SMSUtils.sendByCode(mobile, String.format(MobileLoginUtil.LOGIN_PASSWORD_TEMPLATE,mobile,password));
            // }else{
            // response.fail().msg(ErrorCode.CREATE_ACCOUNT_FAIL.getMessage());
            // return false;
            // }
        }
        return true;
    }

    @Override
    public boolean validatePassword(PasswordRequestVO passwordRequestVO, MobileResponse response) {
        String oldPwd = passwordRequestVO.getOldPwd();
        if (StringUtils.isBlank(oldPwd)) {
            response.fail().msg(ErrorCode.OLD_PASSWORD_NULL_ERROR.getMessage());
            return false;
        }
        if (!passwordRequestVO.getNewPwd().equals(passwordRequestVO.getReNewPwd())) {
            response.fail().msg(ErrorCode.RE_PASSWORD_ERROR.getMessage());
            return false;
        }
        Passport passport = passportService.getById(passwordRequestVO.getPassportId());
        if (passport != null) {
            try {
                if (!JigouPasswordUtil.validatePassword(oldPwd, passport.getPassword())) {
                    response.fail().msg(ErrorCode.OLD_PASSWORD_ERROR.getMessage());
                    return false;
                }
            } catch (NoSuchAlgorithmException e) {
                response.fail().msg(ErrorCode.OLD_PASSWORD_ERROR.getMessage());
                return false;
            } catch (InvalidKeySpecException e) {
                response.fail().msg(ErrorCode.OLD_PASSWORD_ERROR.getMessage());
                return false;
            }
        }

        return true;
    }

    @Override
    public boolean validateResetPassword(ResetPasswordVO resetPasswordVO, MobileResponse response) {
        String code = resetPasswordVO.getCode();
        String password = resetPasswordVO.getPassword();
        String mobile = resetPasswordVO.getMobile();
        if (StringUtils.isBlank(password)) {
            response.fail().msg(ErrorCode.PASSWORD_NULL_ERROR.getMessage());
            return false;
        }
        if (StringUtils.isBlank(mobile)) {
            response.fail().msg(ErrorCode.MOBILE_NULL_ERROR.getMessage());
            return false;
        }
        if (StringUtils.isBlank(resetPasswordVO.getCode())) {
            response.fail().msg(ErrorCode.CODE_NULL_ERROR.getMessage());
            return false;
        }
        if (!password.equals(resetPasswordVO.getRePassword())) {
            response.fail().msg(ErrorCode.RE_PASSWORD_ERROR.getMessage());
            return false;
        }
        if (!MobileLoginUtil.validPasscode(mobile, code)) {
            response.fail().msg(ErrorCode.CODE_INVALID_ERROR.getMessage());
            return false;
        }
        return true;
    }

    @Transactional
    @Override
    public boolean validateBindPassportVo(BindPassportVO bindPassportVO, MobileResponse response,
        HttpServletRequest request) {
        String mobile = bindPassportVO.getMobile();
        String code = bindPassportVO.getCode();
        String thirdId = bindPassportVO.getThird_id();
        String captcha = bindPassportVO.getCaptcha();
        String captcha_code = (String) request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
        if (StringUtils.isBlank(thirdId)) {
            response.fail().msg(ErrorCode.THIRD_UID_NULL_ERROR.getMessage());
            return false;
        }
        if (StringUtils.isBlank(mobile)) {
            response.fail().msg(ErrorCode.MOBILE_NULL_ERROR.getMessage());
            return false;
        }
        if (StringUtils.isBlank(code)) {
            response.fail().msg(ErrorCode.CODE_NULL_ERROR.getMessage());
            return false;
        }
        if (StringUtils.isBlank(captcha)) {
            response.fail().msg(ErrorCode.CAPTCHA_NULL_ERROR.getMessage());
            return false;
        }
        if (!captcha.equalsIgnoreCase(captcha_code)) {
            response.fail().msg(ErrorCode.CAPTCHA_INVALID_ERROR.getMessage());
            return false;
        }
        if (!MobileLoginUtil.validPasscode(mobile, code)) {
            response.fail().msg(ErrorCode.CODE_INVALID_ERROR.getMessage());
            return false;
        }
        if (!passportService.existedUser(mobile, 0)) {// 手机号不存在, 创建新的passport帐号; 手机号已经存在, 直接绑定帐号
            Passport passport = new Passport();
            passport.setMobile(mobile);
            String password = randomStringGenerator.getRandomString(8);
            String pwdHash = JigouPasswordUtil.createHash(password);
            passport.setPassword(pwdHash);
            passport.setMobileVerify(Passport.MobileVerify.YES.getId());
            Long passportId = passportService.createAccount(passport);
            if (passportId > 0) { // 给用户发短信告知密码 bind 第三方登录信息
                passport.setId(passportId);
                if (passportService.synData(passport) <= 0) {
                    response.fail().msg(ErrorCode.SYN_DATA_ERROR.getMessage());
                    return false;
                }
                SMSUtils.sendByCode(mobile, String.format(MobileLoginUtil.LOGIN_PASSWORD_TEMPLATE, mobile, password));
                thirdLoginAccountDao.updatePassportId(passportId, thirdId);
            }
        } else {
            Passport passport = passportDao.findByMobile(mobile);
            Long passportId = passport.getId();
            thirdLoginAccountDao.updatePassportId(passportId, thirdId);
        }

        return true;
    }

    @Override
    public boolean validateCaptcha(HttpServletRequest request, MobileResponse<?> response) {
        String guid = request.getParameter(Credentials.CAPTCHA_GUID);
        if (StringUtils.isNotBlank(guid)) {
            String captchaCode = RedisUtil.hGet(guid, Credentials.CAPTCHA_GUID);
            logger.info("validate captcha code: {}", captchaCode);

            if (StringUtils.isNotBlank(captchaCode) && captchaCode.equals(request.getParameter(Credentials.CAPTCHA))) {
                return true;
            } else {
                response.setCode(ErrorCode.CAPTCHA_INVALID_ERROR.getCode());
                response.setMsg(ErrorCode.CAPTCHA_INVALID_ERROR.getMessage());
            }
        } else {
            response.setCode(ErrorCode.NEED_CAPTCHA.getCode());
            response.setMsg(ErrorCode.NEED_CAPTCHA.getMessage());
        }

        return false;
    }
}